package sweet.mvc

import org.slf4j.{ Logger, LoggerFactory }
import scala.collection.mutable.HashMap

/* Singleton application instance per web application.
 * Here we will hold an implementation of the a config object. */
object ApplicationConfig {
  /* This one must be available without waiting to dynamically loaded. */
  val defaultConfig = new DefaultSweetConfig
  
  /* The config that user applcitation may defined. Can be loaded after
   * config instance is create. */
  private var _config: SweetConfig = null
  
  /* The config instance will only return if it got initialized.*/
  def config = 
    if (_config == null) throw new Exception("config instance is not loaded yet.")
    else _config
  
  /* Initializing the user delegated config from the implementation class instance. */  
  def init(clazz: Class[_]): SweetConfig = {
    if(!classOf[SweetConfig].isAssignableFrom(clazz))
      throw new IllegalArgumentException(clazz +" is not instance of SweetConfig")
    _config = clazz.newInstance.asInstanceOf[SweetConfig]
    _config //return this config instance.
  }
}

/* Trait that define Sweet configuration for all webapp building. */
trait SweetConfig {
   var sweetDispatcherName: String
  
  def controllers: HashMap[String, Controller]
  def viewPrefix: String
  def viewSuffix: String
  
  def init: Unit
  def destroy: Unit
}

/* Default implemenation will provide most practical values. 
 */
class DefaultSweetConfig extends SweetConfig{
  protected val logger = LoggerFactory.getLogger(getClass)
   
  /* Dispatcher name is use to route and search for controller and views.
   * This value should be re-assigne automatically by dispatcher during init.
   * Usualy should match to dispatcherServlet mapping in web.xml. */
  var sweetDispatcherName = "/webapp"
  
  /* Default view paths */
  val viewPrefix = "/view"
  val viewSuffix = ".ftl"
  
  /* mapping of controllers. */
  val controllers = new HashMap[String, Controller]
    
  /* During initialize period, check and insert all default values
   * if subclass did not override/provide any.*/
  def init{
    logger.debug("Config initializing.")
    
    if(!controllers.contains("/main"))
      controllers("/main") = new UrlViewController
      
    logger.debug("Config implementation: " + this)
    logger.debug("Controller and Handlers mappings: ")
    for((kc,c) <- controllers){
      logger.debug("  "+kc+": "+c.getClass)
      for((kh,h) <- c.handlers)
       logger.debug("    "+kh+": "+h.getClass)
    }
  }
  
  /* Do nothing so far. */
  def destroy{
    logger.debug("Config shutting down.")  
  }
    
  /* Allow subclass to add more controller mappings */
  protected def addControllers(ctrls: (String, Controller)*){
    for((k,v) <- ctrls){
      logger.debug("Adding new controller " + k + ": "+v)
      controllers(k) = v
    }
  }
}

